#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2019 crane <crane@gosun>
#
# Distributed under terms of the MIT license.

"""

"""

from collections import defaultdict


L = -1
R =  1
T = 'Still'     # till, 不变化
S = " "



class TransitionTarget:
    def __init__(self, state, write_symbol=S, direction=R):
        self.state = state
        self.write = write_symbol
        self.lr = direction         # -1, 1


AcceptHalt  = TransitionTarget('accept')
RejectHalt  = TransitionTarget('halt')
NotPossible = TransitionTarget('no-possible')


class TuringTransitionTable:
    def __init__(self, transfer_table):
        self.tm = defaultdict()

        for one_line_transfer in transfer_table:
            state, symbol, transition_target = one_line_transfer
            # self.tm.add(state, symbol, transition_target)
            self.add(state, symbol, transition_target)

    def find(self, state, symbol):
        return self.tm.get(state, {}).get(symbol, None)

    def add(self, state, symbol, transition_target):
        self.tm[state] = self.tm.get(state, {})     # 考虑到state不存在的情况
        self.tm[state][symbol] = transition_target


class TuringMachine:
    def __init__(self, transfer_table, start_state):
        self.tf    = transfer_table
        self.start = start_state
        self.cur = start_state
        self.init_data()

    def init_data(self):
        self.cur = self.start       # NOTE: 记得初始化cur, 使得recognise()可以重复使用
        self.head = 0           # tape index

        self.cnt = 0

    def run(self, input):
        self.tape = input
        self.init_data()

        while True:
            ret = self.one_move()
            self.cnt += 1
            if ret in [True, False, 'no-possible']:
                print('transition cnt is ', self.cnt)
                return ret


    def one_move(self):
        symbol = self.tape[self.head]
        target = self.tf.find(self.cur, symbol)
        state, write, lr = target.state, target.write, target.lr

        print("from ==> state ((%s)), symbol [%s]" % (self.cur, symbol))
        print("to symbol [%s], state ((%s)), lr [%s] <==" % (write, state, lr))
        # print(self.tape)

        if state == RejectHalt.state:
            # print("=================== reject halt =====================")
            return False

        if state == AcceptHalt.state:
            # print("=================== accept halt =====================")
            return True

        if state == NotPossible.state:
            # print("=================== accept halt =====================")
            return NotPossible.state

        if target.write != T:
            self.tape[self.head] = write
        else:
            pass
            print("== state [%s], tape not change [%s]" %(self.cur, self.tape[self.head]))
        print('\n')

        self.head += lr
        self.cur = state

        return None


